#include "Buffer.h"
#include "Logger.h"

using namespace devem;

void Buffer::MoveReadOffset(uint64_t len) {
    if (len <= 0 || len > Readable())
        return;
    read_index_ += len;
}

/* 不移动读偏移量 */
void Buffer::Peek(void* buffer, uint64_t len) {
    if (len <= 0 || len > Readable()) {
        LOG_DEBUG("len is %d, not proper for read.", len);
        return;
    }
    // std::copy(iterator source_first, iterator source_end, iterator target_start);
    std::copy(ReadIndex(), ReadIndex() + len, (char*)buffer);
}

void Buffer::Read(void* buffer, uint64_t len) {
    if (len <= 0 || len > Readable()) {
        LOG_DEBUG("len is %d, not proper for read.", len);
        return;
    }
    std::copy(ReadIndex(), ReadIndex() + len, (char*)buffer);
    MoveReadOffset(len);
}

std::string Buffer::PeekString(uint64_t len) {
    std::string str;
    str.resize(len);
    Peek(&str[0], len);
    return str;
}

std::string Buffer::ReadString(uint64_t len) {
    std::string str;
    str.resize(len);
    Read(&str[0], len);
    return str;
}

void Buffer::EnsureSpace(uint64_t len) {
    // #1. 可写区域足够大
    if (len <= Readable())
        return;
    // #2. 可写区域加上预置区域足够大
    else if (len <= Readable() + Prependable()) {
        // step1: 将可读区域拷贝到开头并更新可读偏移量
        uint64_t rsz = Readable();
        std::copy(ReadIndex(), ReadIndex() + rsz, buffer_.begin() + defaultPrependSize);
        read_index_ = defaultPrependSize;
        // step2: 更新可写偏移量
        write_index_ = read_index_ + rsz;
    }
    // #3. 不够，直接扩容
    else {
        LOG_INFO("resize space:%d", write_index_ + len);
        buffer_.resize(write_index_ + len);
    }
}

void Buffer::MoveWriteOffset(uint64_t len) {
    if (len <= 0 || len > Writeable())
        return;
    write_index_ += len;
}

/* 不移动写偏移量 */
void Buffer::Append(const void* buffer, uint32_t len) {
    // 先确保有合适的空间（移动空间 or 直接扩容），再拷贝
    if (len <= 0)
        return;
    EnsureSpace(len);
    std::copy((char*)buffer, (char*)buffer + len, WriteIndex());
}

void Buffer::Write(const void* buffer, uint32_t len) {
    if (len <= 0)
        return;
    EnsureSpace(len);
    std::copy((char*)buffer, (char*)buffer + len, WriteIndex());
    MoveWriteOffset(len);
}

void Buffer::AppendString(const std::string& str) {
    return Append(str.c_str(), str.size());
}

void Buffer::WriteString(const std::string& str) {
    return Write(str.c_str(), str.size());
}